我们与来自各个行业的数十个团队携手,致力于构建大型语言模型(LLM)代理。实践证明,最有效的方案常常是选择简单而灵活的组合模式,而非繁琐的框架。
在本篇文章中,我们将分享从与客户合作及自身构建代理过程中获得的经验,并向开发者提供有关如何构建高效代理的实用建议。
什么是代理(Agent)?
“代理”这一概念可以有多种解释。有些客户将代理视为完全自主的系统,这些系统能够在较长时间内独立运行,并利用多种工具完成复杂任务。而另一些客户则用这个术语来描述遵循预定义工作流程的更具指导性的实现。在Anthropic,我们将这些不同的形式统称为代理系统,但在工作流程和代理之间,我们做出了重要的架构区分:
- 工作流程(Workflows) 是指,通过预设的代码路径来协调大型语言模型(LLM)与各种工具。
- 代理(Agents) 是指,大型语言模型(LLM)能够动态地指挥自己的流程和工具使用,从而保持对任务完成方式的控制。
接下来,我们将深入探讨这两种类型的代理系统。在附录1(“实践中的代理”)中,我们将阐述客户在使用这些系统时所获得的两个特别有价值的领域。
何时使用代理(Agent)
在构建大型语言模型(LLM)应用时,我们建议首先寻找最简单的解决方案,只有在确实需要时才考虑增加复杂性。这可能意味着您根本不需要构建代理系统。代理系统通常会在延迟和成本上进行取舍,以实现更好的任务性能,因此您需要仔细评估这种权衡在何时是合理的。
当更多复杂性是必要的时,工作流程(Workflows)为清晰定义的任务提供了可预测性和一致性,而在需要灵活性和大规模模型驱动决策的情况下,代理(Agents)则是更好的选择。然而,对于许多应用,通过检索和上下文示例来优化单次LLM调用通常已经足够。
何时以及如何使用框架
有许多框架可以使代理系统的实现变得更加简单,包括:
- LangChain 的 LangGraph;
- 亚马逊 Bedrock 的 AI Agent framework;
- Rivet,一个拖放式图形用户界面(GUI)大型语言模型(LLM)工作流构建工具;
- Vellum,另一个用于构建和测试复杂工作流的 GUI 工具。
这些框架通过简化调用 LLM、定义和解析工具以及将调用串联在一起等标准低级任务,使得入门变得更加容易。然而,它们通常会引入额外的抽象层,可能会掩盖底层的提示和响应,从而使调试变得更加困难。此外,这些框架有时会诱使开发者在实际不需要的情况下增加复杂性。
我们建议开发者优先直接使用 LLM API,因为许多常见模式可以用几行代码实现。如果您选择使用框架,请确保理解其底层代码,因为对这些实现的错误假设常常是客户出错的主要原因。
有关一些示例实现,请查阅我们的手册 。
青玄注:
手册的主要围绕以下内容,参考意义较高
- 基本构建模块
- 提示链
- 路由
- 多LLM并行化
- 高级工作流
- 协调者-子代理
- 评估者-优化器
构建模块、流程(workflows)与智能代理(agent)
在这一部分,我们将深入探讨在实际应用中常见的智能系统模式。首先,我们会介绍基础构建模块——增强型大语言模型,接着逐步探讨从简单的组合流程到自主智能代理。
构建块:增强型大语言模型
智能系统的基本构建块是增强型大语言模型(增LLM),具备检索、工具和记忆等多种功能。现有模型能够主动运用这些能力,生成搜索查询、选择合适的工具,并判断哪些信息值得保留。
我们建议关注实施的两个重点:一是根据您的具体用例定制这些功能,二是确保为您的大语言模型提供简洁且文档完善的接口。虽然有多种方法可以实现这些增强功能,但我们最近发布的模型上下文协议提供了一种有效的解决方案,使开发者能够通过简单的客户端实现与日益丰富的第三方工具生态系统进行集成。
在接下来的内容中,我们将假设每次大语言模型(LLM)的调用都可以访问这些增强功能。
笔者注:上下文协议,以及上下文协议的客户端实现需要展开
青玄注:
模型上下文协议(MCP),以及基于MCP的实践,对于工作流乃至智能体的建设都具备很好的指导意义
工作流:提示链
提示链是一种有效的任务分解方法,将复杂的任务拆分为多个步骤。每个大型语言模型(LLM)的调用都会处理前一步骤的结果。同时,您可以在各个中间步骤中设置程序性检查(如下图所示的“Gate”),以确保整个流程始终保持在预期轨道上。
何时使用
此工作流程非常适合轻松、清晰地将任务分解为固定子任务的场景。其主要目标是通过简化每个大型语言模型(LLM)的调用,来降低延迟并提高准确性。
应用示例
提示链可以在以下场景中发挥重要作用:
- 生成营销文案,随后将其翻译成另一种语言。
- 首先撰写文档大纲,检查大纲是否符合特定标准,然后根据大纲撰写完整文档。
工作流: 路由
路由是一种将输入进行分类并引导到专门后续任务的机制。这种工作流程可以实现关注点的分离,并构建更加专业化的提示。在没有这种工作流程的情况下,针对某一类输入的优化可能会影响到其他类型输入的性能。
何时使用
路由特别适用于复杂任务,这些任务存在明显的类别,且这些类别的处理效果更佳,分类工作可以通过大型语言模型(LLM)或传统的分类模型/算法准确完成。
应用示例
路由可以在以下场景中发挥重要作用:
- 将不同类型的客户服务查询(如一般问题、退款请求、技术支持)导入各自不同的下游流程、提示和工具中。
- 将简单或常见问题路由到较小的模型(例如 Claude 3.5 Haiku),而将复杂或不寻常的问题分配给更强大的模型(例如 Claude 3.5 Sonnet),以优化成本和响应速度。
工作流: 并行化
大型语言模型(LLM)有时可以在同一任务上同时工作,并通过编程方式汇总输出。这种工作流程称为并行化,主要有两种形式:
- 分块:将任务拆分为独立的子任务并行处理。
- 投票:对同一任务进行多次处理,以获取多样化的结果。
何时使用此工作流程
并行化适用于以下情况:当任务可以被拆分为并行处理的子任务以加快速度,或当需要多种视角或尝试以提高结果的置信度时。对于复杂任务,通常情况下,分开处理每个考虑因素会使 LLM 的表现更佳,从而让每个特定方面获得更深入的关注。
应用示例
并行化在以下场景中尤为有效:
分块实例:
- 设置保护机制,一台模型实例负责处理用户查询,而另一台则专注于筛查不当内容或请求,这样的分工通常比同一个 LLM 同时处理保护和核心响应效果更好。
- 自动化评估系统,评估 LLM 在不同提示下的性能,每个 LLM 调用关注模型性能的不同方面。
投票实例:
- 对代码进行漏洞检查,通过多个不同的提示来审查代码,发现问题时进行标记。
- 评估某段内容是否不当,使用多种提示从不同角度进行评估,或设定不同的投票阈值,以平衡假阳性和假阴性。
工作流:协调者-工作者
在协调者-工作者的工作流程中,中央大型语言模型(LLM)动态地将任务拆分,分配给工作者 LLM,并综合它们的结果。
何时使用
该工作流程特别适合复杂任务,当难以预测所需的子任务时(例如,在编码过程中,需要更改的文件数量以及每个文件的更改类型可能与具体任务相关联)。与并行化的主要区别在于协调者的灵活性子任务是由协调者根据特定输入动态确定的,而不是预先定义的。
实际应用示例
协调者-工作者工作流程在以下场景中尤为有效:
- 进行编码时,每次对多个文件进行复杂更改。
- 在搜索任务中,涉及从多个来源收集和分析信息,以获取可能相关的信息。
工作流程:评估器-优化器
在评估器-优化器的工作流程中,一个大型语言模型(LLM)负责生成响应,而另一个模型则在循环中进行评估和反馈。
何时使用
这一工作流程特别适合在有明确评估标准的情况下使用,同时迭代改进能够带来可衡量的益处。其适用的两个标志是: 第一,LLM 的响应在获得人类反馈后能明显改善; 第二,LLM 能够有效提供这样的反馈。 这与人类作家在创作精炼文档时所经历的迭代写作过程相似。
实际应用示例
评估者-优化器工作流程在以下场景中尤为有效:
- 文学翻译:翻译 LLM 可能初始未能捕捉到的细微差别,评估 LLM 可以提供宝贵的批评。
- 复杂搜索任务:需要进行多轮搜索和分析以收集全面信息,评估者决定是否需要进一步的搜索。
Agents 代理
随着大型语言模型(LLM)在关键能力上的成熟,代理在生产环境中逐渐得到应用。这些能力包括理解复杂输入、进行推理和规划、可靠使用工具,以及从错误中恢复。代理的工作开始于人类用户的命令或互动讨论。当任务明确后,代理将独立进行规划和操作,可能在执行过程中需要返回人类获取进一步的信息或判断。
在执行的过程中,代理必须在每一步都从环境中获取“真实信息”(例如工具调用的结果或代码执行的结果),以评估进展。代理可以在检查点或遇到障碍时暂停,以获取人类反馈。任务通常在完成时终止,但常常会设定停止条件(例如最大迭代次数)以保持对任务的控制。
代理能够处理复杂任务,但其实施过程往往相对简单。它们通常只是基于环境反馈循环使用工具的 LLM。因此,清晰且周到地设计工具集及其文档是至关重要的。我们在附录2(“为您的工具进行提示工程”)中进一步探讨了工具开发的最佳实践。
何时使用
代理适用于开放性问题,这类问题难以预测所需步骤,也无法预设固定路径。LLM可能需要多次操作,因此需对其决策能力有一定信任。代理的自主性使其在受信任的环境中扩展任务时表现优异。
然而,代理的自主性也意味着更高的成本和错误累积的风险。我们建议在沙盒环境中进行充分测试,并设置必要的防护措施。
实际应用示例
- 编码代理:用于解决SWE-bench tasks任务,根据任务描述对多个文件进行编辑。
- “计算机使用”参考实现:Claude通过计算机完成任务。 通过优化,译文更加简洁、流畅,符合中文语言习惯,同时保留了原文的核心信息。
青玄注:
沙盒环境不论是测试阶段还是实际应用智能体的即阶段都是需要重点关注的内容,比如文中所提实践,以及e2b.dev的工具实践
组合与定制这些模式
这些构建模块并非固定模板,而是开发者可根据不同场景灵活组合的常见模式。与任何LLM功能一样,成功的关键在于不断衡量性能并迭代优化。切记:只有在明确能带来显著提升时,才应考虑增加复杂性。
摘要
在LLM领域,成功之道在于构建适合需求的系统,而非一味追求复杂。从简单的提示词入手,通过全面评估优化,仅当更简单的解决方案无法满足需求时,才考虑引入多步骤的代理系统。
在实施代理时,我们遵循三大核心原则:
- 保持设计简洁,避免过度复杂化。
- 优先透明度,明确展示代理的规划步骤。
- 通过详尽的工具文档和测试,精心设计代理-计算机接口(ACI)。
框架虽能助你快速上手,但在进入生产环境时,不妨减少抽象层,使用基础组件构建。遵循这些原则,你可以创建功能强大、可靠、可维护且赢得用户信任的代理。
致谢
作者:Erik Schluntz和Barry Zhang。本文基于我们在Anthropic构建代理的经验,以及客户分享的宝贵见解,对此我们深表感谢。
附录1:代理的实际应用
我们与客户的合作揭示了两种特别有前景的AI代理应用,展示了上述模式的实际价值。这两种应用都说明了代理在需要对话和行动、有明确成功标准、支持反馈循环并整合有意义的人类监督的任务中如何发挥最大价值。
A. 客户支持
客户支持将熟悉的聊天机器人界面与通过工具集成增强的功能相结合。这非常适合更开放的代理,因为:
- 支持交互自然遵循对话流程,同时需要访问外部信息和操作;
- 可以集成工具以提取客户数据、订单历史记录和知识库文章;
- 诸如退款或更新工单等操作可以通过程序化方式处理;
- 成功可以通过用户定义的解决方案明确衡量。
多家公司已通过基于使用量的定价模型展示了这种方法的可行性,该模型仅对成功的解决方案收费,表明对其代理有效性的信心。
B. 编码代理
- 软件开发领域展示了LLM功能的显著潜力,其能力从代码补全发展到自主问题解决。代理特别有效,因为:
- 代码解决方案可以通过自动化测试验证;
- 代理可以使用测试结果作为反馈迭代解决方案;
- 问题空间定义明确且结构化;
- 输出质量可以客观衡量。
在我们的实现中,代理现在可以仅根据拉取请求描述解决SWE-bench Verified基准测试中的真实GitHub问题。然而,尽管自动化测试有助于验证功能,但人类审查对于确保解决方案符合更广泛的系统要求仍然至关重要。
附录2:工具的提示工程
无论你构建哪种代理系统,工具都可能成为代理的重要组成部分。工具使Claude能够通过在我们的API中指定其确切结构和定义与外部服务和API交互。当Claude响应时,如果它计划调用工具,它将在API响应中包含一个工具使用块。工具定义和规范应与整体提示一样受到提示工程的关注。在本附录中,我们描述了如何对工具进行提示工程。
通常有几种方法可以指定相同的操作。例如,你可以通过编写差异或重写整个文件来指定文件编辑。对于结构化输出,你可以在Markdown或JSON中返回代码。在软件工程中,这些差异是表面上的,可以无损地相互转换。然而,某些格式对于LLM来说比其他格式更难编写。编写差异需要知道在编写新代码之前块头中有多少行正在更改。在JSON中编写代码(与Markdown相比)需要对换行符和引号进行额外的转义。
我们关于决定工具格式的建议如下:
- 给模型足够的标记来“思考”,以免它陷入困境;
- 保持格式接近模型在互联网文本中自然看到的内容;
- 确保没有格式“开销”,例如必须准确计算数千行代码或对编写的任何代码进行字符串转义。
一个经验法则是考虑人机界面(HCI)需要多少努力,并计划在创建良好的代理-计算机界面(ACI)上投入同样的努力。以下是一些关于如何做到这一点的想法:
- 站在模型的角度思考。根据描述和参数,使用此工具是否显而易见,还是需要仔细思考?如果是后者,那么模型也可能如此。一个好的工具定义通常包括示例用法、边缘情况、输入格式要求以及与其他工具的明确界限。
- 如何更改参数名称或描述以使事情更明显?将其视为为团队中的初级开发人员编写优秀的文档字符串。在使用许多类似工具时,这一点尤其重要。
- 测试模型如何使用你的工具:在我们的工作台中运行许多示例输入,以查看模型犯的错误并进行迭代。
- 为你的工具设计防错机制。更改参数以减少错误的可能性。
在构建我们的SWE-bench,代理时,我们实际上花在优化工具上的时间比整体提示更多。例如,我们发现当代理移出根目录后,模型在使用相对文件路径的工具时会犯错误。为了解决这个问题,我们将工具更改为始终要求绝对文件路径——我们发现模型使用这种方法时完美无缺。
原文 https://www.anthropic.com/engineering/building-effective-agents